package com.linq.cool.pay.service;

import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.builder.AlipayTradeRefundRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.model.result.AlipayF2FRefundResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.linq.cool.common.core.domain.Result;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.http.HttpStatus;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: yqlin
 * @Date: 2021/1/20 21:42
 * @Description:
 * @Version: 1.0.0
 */
public class AlipayService {
    private static final Log log = LogFactory.getLog("trade_precreate");
    /**
     * 支付宝当面付对象
     */
    private static final AlipayTradeService tradeService;
    /**
     * 商户操作员编号，添加此参数可以为商户操作员做销售统计
     */
    private static final String operatorId = "test_operator_id";
    /**
     * (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持
     */
    private static final String storeId = "test_store_id";
    /**
     * 支付超时，定义为120分钟
     */
    private static final String timeoutExpress = "120m";

    static {
        Configs.init("ali-pay.properties");
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
    }

    /**
     * 支付的方法
     *
     * @param outTradeNo           (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，
     *                             需保证商户系统端不能重复，建议通过数据库sequence生成，
     * @param subject              (必填) 订单标题，粗略描述用户的支付目的。如“喜士多（浦东店）消费”
     * @param totalAmount          （必填) 订单总金额，单位为元，不能超过1亿元，如果同时传入了【打折金额】,
     *                             【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
     * @param undiscountableAmount (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段，
     *                             如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
     * @param body                 订单描述，可以对交易或商品进行一个详细地描述，比如填写"购买商品2件共15.00元"
     * @param notifyUrl            支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
     *
     * @return 结果
     */
    public static Result<?> pay(String outTradeNo,
                                String subject,
                                String totalAmount,
                                String undiscountableAmount,
                                String body,
                                String notifyUrl
    ) {
        AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                .setSubject(subject)
                .setTotalAmount(totalAmount)
                .setOutTradeNo(outTradeNo)
                .setUndiscountableAmount(undiscountableAmount)
                .setBody(body)
                .setOperatorId(operatorId)
                .setStoreId(storeId)
                .setTimeoutExpress(timeoutExpress)
                // 支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
                .setNotifyUrl(notifyUrl);
        // .setNotifyUrl("http://www.test-notify-url.com");
        // 发起支付
        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝预下单成功: )");
                AlipayTradePrecreateResponse res = result.getResponse();
                // 得到支付码,本质就是一个url
                String zfbQrCode = res.getQrCode();
                Map<String, Object> map = new HashMap<>(2);
                map.put("zfb_qrCode", zfbQrCode);
                return Result.ok(map, "支付宝预下单成功");
            case FAILED:
                log.error("支付宝预下单失败!!!");
                return Result.fail("支付宝预下单失败");
            case UNKNOWN:
                log.error("系统异常，预下单状态未知!!!");
                return Result.fail(HttpStatus.NOT_FOUND.value(), "系统异常，预下单状态未知");
            default:
                log.error("不支持的交易状态，交易返回异常!!!");
                return Result.fail(HttpStatus.NOT_FOUND.value(), "不支持的交易状态，交易返回异常");
        }
    }


    /**
     * 退费
     *
     * @param outTradeNo   外部应该交易ID
     * @param tradeNo      平台在支付成之后返回的平台【属于支付宝平台的ID】
     * @param refundAmount 退款金额
     * @param refundReason 退款原因
     * @param outRequestNo 是否支持部分退款
     *
     * @return 结果
     */
    public static Result<?> payBack(String outTradeNo,
                                    String tradeNo,
                                    String refundAmount,
                                    String refundReason,
                                    String outRequestNo
    ) {
        AlipayTradeRefundRequestBuilder builder = new AlipayTradeRefundRequestBuilder()
                //outTradeNo tradeNo只需要有一个就行
                .setOutTradeNo(outTradeNo)
                .setTradeNo(tradeNo)
                .setRefundAmount(refundAmount)
                .setRefundReason(refundReason)
                .setOutRequestNo(outRequestNo)
                .setStoreId(storeId);
        //退费请求
        AlipayF2FRefundResult result = tradeService.tradeRefund(builder);
        switch (result.getTradeStatus()) {
            case SUCCESS:
                log.info("支付宝退款成功: )");
                return Result.ok("支付宝退款成功");
            case FAILED:
                log.error("支付宝退款失败!!!");
                return Result.fail(result.getResponse().getSubMsg());
            case UNKNOWN:
                log.error("系统异常，订单退款状态未知!!!");
                return Result.fail(result.getResponse().getSubMsg());
            default:
                log.error("不支持的交易状态，交易返回异常!!!");
                return Result.fail(result.getResponse().getSubMsg());
        }
    }

}
